package jk.fox.invocation.proxy;


import jk.fox.node.client.RpcCluster;
import jk.fox.node.node.RpcNode;
import jk.fox.common.ReflectionUtils;
import jk.fox.common.exception.runtime.RpcModuleNotInitException;
import jk.fox.engine.RpcNodeDefinition;
import jk.fox.invocation.Invocation;
import org.apache.log4j.Logger;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/**
 * @author cuichao
 * @Description: RpcJdkProxy
 * @Date: create in 2020/4/12 14:01
 */
public class RpcJdkProxy implements InvocationHandler {
    private static Logger logger = Logger.getLogger(RpcJdkProxy.class);

    private String domain;
    private RpcNode node;
    private Invocation invocation;
    private RpcNodeDefinition definition;


    public RpcJdkProxy(Invocation invocation, RpcNodeDefinition definition){
        this.invocation = invocation;
        this.definition = definition;
    }



    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //lazy RpcNode and domain at called
        if(invocation.cluster() == null ){
            throw new RpcModuleNotInitException(String.format("%s has not init", RpcCluster.class.getName()));
        }
        if(node == null){
            this.node = invocation.cluster().addNode(definition);
            this.domain = node.getDomain();
        }

        //前置增强
        //前置增强

        //判断是否同源调用
        if(hasSameSource()){
            logger.info(String.format("because %s.%s match same source call, execute native invoker", domain,method.getName()));
            Object response = invocation.local(domain,method,args);
            //后置增强
            //后置增强
            return response;
        }

        //Rpc调用
        logger.info(String.format("because %s.%s is not match same source call, execute rpc invoker", domain,method.getName()));
        String path = domain+"/"+method.getName();
        String[] parameterTypes = ReflectionUtils.getParameterTypes(method);
        Object response = invocation.cluster().execute(path,node,args,parameterTypes);
        //Rpc调用

        //后置增强
        //后置增强
        return response;
    }

    protected boolean hasSameSource(){
        return node.hasSameSource();
    }


}
